import { VNodeDirective } from '@/interface/types/vnode';
interface IClickOutsideElmenet extends HTMLElement {
  _clickOutside?: (this: HTMLElement, ev: MouseEvent) => any;
}

const defaultConditional = () => true;

function directive (e: PointerEvent, el: HTMLElement, binding: VNodeDirective): void {
  const handler = typeof binding.value === 'function' ? binding.value : binding.value!.handler;

  const isActive = (typeof binding.value === 'object' && binding.value.closeConditional) || defaultConditional;
  
  if (!e || isActive(e) === false) return;
  const elements = ((typeof binding.value === 'object' && binding.value.include) || (() => []))();
  elements.push(el);

  !elements.some((el: HTMLElement) => el.contains(e.target as Node)) && setTimeout(() => {
    isActive(e) && handler && handler(e)
  }, 0);
}

const mounted = (el: IClickOutsideElmenet, binding: VNodeDirective) => {
  const onClick = (e: Event) => directive(e as PointerEvent, el, binding);
  // 当body的子节点发生点击事件的时候, 让body优先处理
  document.body.addEventListener('click', onClick, true);
  el._clickOutside = onClick;
}
const beforeUnmount = (el: IClickOutsideElmenet, binding: VNodeDirective) => {
  if (!el._clickOutside) return;
  const app = document.body;
  app && app.removeEventListener('click', el._clickOutside, true);
  delete el._clickOutside;
}
export const ClickOutside = {
  mounted,
  beforeUnmount
}